package com.jews.securityleam.authentication.sms;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jews.securityleam.AuthUrlEnum;
import com.jews.securityleam.starter.base.CustomAuthenticationFailureHandler;
import com.jews.securityleam.starter.base.CustomAuthenticationSuccessHandler;
import com.jews.securityleam.starter.config.AuthErrorMsg;
import com.jews.securityleam.starter.exception.MethodNotSupportException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;

@Slf4j
public class SmsLoginProcessFilter extends AbstractAuthenticationProcessingFilter {

    private final CustomAuthenticationSuccessHandler successHandler;
    private final CustomAuthenticationFailureHandler failureHandler;

    public SmsLoginProcessFilter(AuthenticationManager authenticationManager,
                                    CustomAuthenticationSuccessHandler successHandler,
                                    CustomAuthenticationFailureHandler failureHandler) {
        super(AuthUrlEnum.SMS.getUrl(), authenticationManager);
        this.successHandler = successHandler;
        this.failureHandler = failureHandler;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException {
        log.info("前端请求url:{}，uri:{}", request.getRequestURL(), request.getRequestURI());
        checkMethod(request);
        ObjectMapper mapper = new ObjectMapper();
        SmsAuthRequest loginRequest = mapper.readValue(request.getReader(), SmsAuthRequest.class);
        SmsToken token = new SmsToken(loginRequest, Collections.emptyList());
        return this.getAuthenticationManager().authenticate(token);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication authResult) throws IOException {
        successHandler.onAuthenticationSuccess(request, response, authResult);
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException failed) throws IOException {
        SecurityContextHolder.clearContext();
        failureHandler.onAuthenticationFailure(request, response, failed);
    }

    public void checkMethod(HttpServletRequest request) {
        if (!HttpMethod.POST.name().equals(request.getMethod())) {
            throw new MethodNotSupportException(AuthErrorMsg.methodNotSupport.getName());
        }
    }
}
